#include <iostream>
#include <functional>

using std::cout;
using std::endl;
using std::bind;

//bind可以绑定1~n元函数，可以是成员函数，可以是数据成员
//bing通过减少参数列表的参数个数，从而改变了函数形态
//如果不使用占位符，则bind在绑定时要传入全部参数，即最终得到无参函数

/*
template< class F, class... Args >
/unspecified/ bind( F&& f, Args&&... args );

在 C++ 中，unspecified 表示未指明的类型。
在标准库中，有时候函数的返回类型可能会根据传入的参数类型而有所不同，因此无法在函数签名中明确指定返回类型。
这时就会使用 unspecified 表示返回类型未指明，具体的返回类型将根据上下文和参数类型进行推断。
对于 std::bind 函数来说，它的返回类型是一个函数对象，
这个函数对象将会根据传入的参数类型、函数类型等来推断最终的类型。
因此，std::bind 函数的返回类型是未指明的，而是根据具体的调用情况来确定的。
*/

int add(int x, int y)
{
    cout << "int add(int, int)" << endl;
    return x + y;
}

int func(int x, int y, int z)
{
    cout << "int func(int, int, int)" << endl;
    return x * y * z;
}

class Example
{
public:
    // static int add(int x, int y)

    //隐含了this指针
    int add(int x, int y)
    {
        cout << "int Example::add(int, int)" << endl;
        return x + y;
    }
};

void test()
{
    //函数的形态（类型）由两者决定:函数的返回类型 + 参数列表
    //其中参数列表又分为：参数的个数、参数的顺序、参数的类型

    // &(bind(&add, 1, 3));   报错，说明bind的结果是临时对象
    //auto f = bind(add, 1, 3);
    //C中的函数，函数名就是函数的入口地址
    auto f = bind(&add, 1, 3);
    cout << "f() = " << f() << endl;
    //int(int, int)--->int()，参数已经传完了，相当于是无参的，函数形态改变了

    cout << endl;
    auto f2 = bind(func, 10, 20, 30);
    cout << "f2() = " << f2() << endl;

    cout << endl;
    Example ex;
    auto f3 = bind(&Example::add, &ex, 30, 70); //绑定非静态函数时需要把this指针也传入
    cout <<"f3() = " << f3() << endl;
}

int main()
{
    test();
    return 0;
}


